﻿// Copyright 2008 ESRI 
//  
// All rights reserved under the copyright laws of the United States 
// and applicable international laws, treaties, and conventions. 
//  
// You may freely redistribute and use this sample code, with or 
// without modification, provided you include the original copyright 
// notice and use restrictions. 
//  
// See use restrictions at <your ArcGIS install location>/developerkit/userestrictions.txt. 
//  

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using ESRI.ArcGIS.ADF.Web;
using ESRI.ArcGIS.ADF.Web.UI.WebControls;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.Geometry;


//Common API 
using ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools;

//Specific API 
using ESRI.ArcGIS.ADF.ArcGISServer;
using ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using System.Collections.Specialized;
using ESRI.ArcGIS.Geometry;

namespace WebMapApp
{
    /// <summary> 
    /// Summary description for MapGeoEditControl 
    /// </summary> 
    [ToolboxData("<{0}:MapGeoEdit runat=server></{0}:MapGeoEdit>")]
    public class MapGeoEdit : ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl
    {
        #region Member variables that can be customized

        /* Column names to exclude from Identify. 
         * "Display Column", "GRAPHICS_ID", "IS_SELECTED" and columns of type ADF geometry are already set by the framework to not be visible. 
         * GraphicsLayer.GetContentsTemplate honors this visibility setting.*/
        private string[] m_excludedColumnNames = { "OID", "ObjectID",  
            "#ID#" ,  
            "#SHAPE#"};//likely of type IMS geometry 

        private string m_identifyIconUrl = "images/identify-map-icon.png";
        private string m_waitIconUrl = "images/callbackActivityIndicator2.gif";
        private int m_IdentifyTolerance = 2; // tolerance used in identify request... may need to be adjusted to a specific resource type 
        private IdentifyOption m_idOption = IdentifyOption.VisibleLayers;
        private string m_mapBuddyId = "Map1";
        private string m_taskResultsId = "TaskResults1";
        private int m_numberDecimals = 3; //number of decimals in coordinate string 
        private bool m_isRTL = false;
        private string EditLayer = "ÈË¹¤Óă½¸Çø";
        private string FieldsValue = "¹¤³̀Ăû³Æ:ĐÂÔö¶ÔÏó";
        private string ObjectID = "";
        private string EditType = "";

        #endregion

        #region Member variables
        MapResourceManager m_resourceManger;
        public string m_id;
        private ESRI.ArcGIS.ADF.Web.UI.WebControls.Map m_map;
        private TaskResults m_taskResults;
        #endregion

        public MapGeoEdit()
        {
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            m_id = this.ClientID;
            // find the map, task results and map resource manager controls 
            m_map = Page.FindControl(m_mapBuddyId) as ESRI.ArcGIS.ADF.Web.UI.WebControls.Map;
            m_taskResults = FindControlRecursive(Page, m_taskResultsId) as TaskResults;
            m_resourceManger = m_map.MapResourceManagerInstance;

            #region Register script for creating script object
            ScriptManager sm = ScriptManager.GetCurrent(this.Page);
            if (sm != null) sm.RegisterAsyncPostBackControl(this);
            //string create = String.Format("\nSys.Application.add_init(function() {{\n\t$create(ESRI.ADF.UI.MapGeoEditTool,{{\"id\":\"{3}\",\"uniqueID\":\"{0}\",\"callbackFunctionString\":\"{1}\",\"identifyIcon\":\"{4}\",\"waitIcon\":\"{5}\"}},null,{{\"map\":\"{2}\"}});\n\tMapGeoEditTool = function() {{ $find('{3}').startIdentify(); }};\n }});\n", 
            //this.UniqueID, this.CallbackFunctionString, m_map.ClientID, this.ClientID, m_identifyIconUrl, m_waitIconUrl); 
            string create = String.Format("\nSys.Application.add_init(function() {{\n\t$create(ESRI.ADF.UI.MapGeoEditTool,{{\"id\":\"{3}\",\"uniqueID\":\"{0}\",\"callbackFunctionString\":\"{1}\",\"identifyIcon\":\"{4}\",\"waitIcon\":\"{5}\"}},null,{{\"map\":\"{2}\"}});\n\tMapGeoEditTool = function() {{ $find('{3}').startGeoEdit(); }};\n }});\n",
                this.UniqueID, this.CallbackFunctionString, m_map.ClientID, this.ClientID, m_identifyIconUrl, m_waitIconUrl);

            Page.ClientScript.RegisterStartupScript(this.GetType(), this.Id + "_startup", create, true);
            #endregion
        }

        private Control FindControlRecursive(Control root, string id)
        {
            if (root.ID == id)
            {
                return root;
            }
            foreach (Control c in root.Controls)
            {
                Control t = FindControlRecursive(c, id);
                if (t != null)
                {
                    return t;
                }
            }
            return null;
        }


        protected override void Render(HtmlTextWriter writer)
        {
            //support script file 
            writer.WriteLine("<script type=\"text/javascript\" src=\"JavaScript/MapIdentify.js\"></script>");
        }

        //private string AddNew(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map map, IGISResource resource, IFeatureLayer fl, string xyString, IServerContext serverContext)
        //{
        //    IFeatureClass featureclass = fl.FeatureClass as IFeatureClass;
        //    IFeature feature = featureclass.CreateFeature();
        //    ESRI.ArcGIS.ADF.Web.Geometry.Geometry geometry = GeometryConvert.getWebGeometry(xyString, EditType);
        //    geometry.SpatialReference = map.SpatialReference;
        //    ESRI.ArcGIS.Geometry.IGeometry objgeo = (ESRI.ArcGIS.Geometry.IGeometry)ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.ToIGeometry(geometry, serverContext);
        //    feature.Shape = objgeo;
        //    SetFeatureFieldValue(FieldsValue, resource, feature);
        //    feature.Store();
        //    return feature.OID.ToString();
        //}

        private void DelObjGeo(IFeatureLayer fl, string objectid)
        {
            IFeatureClass pFeatCls = fl.FeatureClass;
            IFeature feature;
            feature = pFeatCls.GetFeature(int.Parse(objectid));
            feature.Delete();//̉ªËØÉ¾³ư´úÂë 
            //É¾³ửªËØµÄÍ¬Ê±É¾³ư¹ØÁª±íÀïĂæµÄÄÚÈƯ 
            //ÓĐ´ưÍêÉÆ 
        }

        //private void SaveAttribute(IGISResource resource, IFeatureLayer fl, string objectid)
        //{
        //    IFeatureClass pFeatCls = fl.FeatureClass;
        //    IFeature feature;
        //    feature = pFeatCls.GetFeature(int.Parse(objectid));
        //    SetFeatureFieldValue(FieldsValue, resource, feature);
        //    feature.Store();
        //}


        //private void UpdateGeo(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map map, IGISResource resource, IFeatureLayer fl, string xyString, string objectid, IServerContext serverContext)
        //{
        //    IFeatureClass pFeatCls = fl.FeatureClass;
        //    IFeature feature;
        //    feature = pFeatCls.GetFeature(int.Parse(objectid));
        //    ESRI.ArcGIS.Geometry.IGeometry objgeo = feature.Shape;
        //    //½«´«»ØÀ´µÄ×ø±ê¸ú¾ƯÔ­Ê¼Í¼ĐÎµÄÀàĐÍ½øĐĐ×ª»»£¬È»ºó¸üĐÂÍ¼ĐÎ getWebGeometryrº¯ÊưÓĐ´ư¸Ä½ø 
        //    ESRI.ArcGIS.ADF.Web.Geometry.Geometry geometry = GeometryConvert.getWebGeometry(xyString, objgeo.GeometryType.ToString());
        //    geometry.SpatialReference = map.SpatialReference;
        //    objgeo = (ESRI.ArcGIS.Geometry.IGeometry)ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.ToIGeometry(geometry, serverContext);
        //    feature.Shape = objgeo;

        //    SetFeatureFieldValue(FieldsValue, resource, feature);
        //    feature.Store();
        //}

        private string getMaxBH(DataTable resultDt, string fieldName)
        {
            var strMaxBH = "";
            for (int i = 0; i < resultDt.Rows.Count; i++)
            {
                if (strMaxBH == "")
                {
                    strMaxBH = resultDt.Rows[i][fieldName].ToString();
                }
                else if (strMaxBH.CompareTo(resultDt.Rows[i][fieldName].ToString()) < 0)
                {
                    strMaxBH = resultDt.Rows[i][fieldName].ToString();
                }

            }
            return strMaxBH;
        }

        //»ñÈ¡ÈË¹¤Óă½¸µÄ±àÂë 
        //private string getRGYJBH(IGISResource resource, string strBH, int QZlen, int HZlen)
        //{
        //    string StrTempBH = strBH;


        //    ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality =
        //       (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)resource.CreateFunctionality(
        //       typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);

        //    ESRI.ArcGIS.ADF.Web.SpatialFilter spatialFilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter();
        //    spatialFilter.ReturnADFGeometries = false;
        //    spatialFilter.WhereClause = "left(±àÂë," + QZlen + ")='" + strBH + "'";// order by ±àÂë desc "; 
        //    string strLsyerid = PublicFun.getStrLayerID(commonQueryFunctionality, EditLayer);
        //    System.Data.DataTable resultsDataTable = commonQueryFunctionality.Query(null, strLsyerid, spatialFilter);
        //    if (resultsDataTable != null && resultsDataTable.Rows.Count > 0)
        //    {
        //        try
        //        {
        //            StrTempBH = getMaxBH(resultsDataTable, "±àÂë");// resultsDataTable.Rows[resultsDataTable.Rows.Count - 1]["±àÂë"].ToString(); 
        //            int strLen = StrTempBH.Length - strBH.Length;
        //            StrTempBH = StrTempBH.Substring(strBH.Length);
        //            StrTempBH = "0000000000000000000000" + (int.Parse(StrTempBH) + 1).ToString();
        //            StrTempBH = StrTempBH.Substring(StrTempBH.Length - strLen);
        //            StrTempBH = strBH + StrTempBH;
        //        }
        //        catch (Exception ex)
        //        {
        //            StrTempBH = strBH + "00000000000".Substring(0, HZlen - 1) + "1";
        //        }
        //    }
        //    else
        //    {
        //        StrTempBH = strBH + "00000000000".Substring(0, HZlen - 1) + "1";
        //    }
        //    return StrTempBH;
        //}

        //ÉèÖẲªËØÊôĐÔ 
        //private void SetFeatureFieldValue(string FieldsValue, IGISResource resource, IFeature feature)
        //{
        //    //System.Collections.Generic.Dictionary<string, string> FieldItems=new System.Collections.Generic.Dictionary<string,string>(); 
        //    try
        //    {
        //        if (FieldsValue != null && FieldsValue != "")
        //        {
        //            //FieldsValue = PublicFun.DecodeUrl(FieldsValue); 
        //            Array keyValuePairs = FieldsValue.Split(",".ToCharArray());
        //            for (int i = 0; i < keyValuePairs.Length; i++)
        //            {
        //                if (!keyValuePairs.GetValue(i).ToString().Equals(""))
        //                {
        //                    string[] strTmp = keyValuePairs.GetValue(i).ToString().Split(":".ToCharArray());
        //                    if (strTmp.Length == 2)
        //                    {
        //                        string strValue = PublicFun.DecodeUrl(strTmp.GetValue(1).ToString());
        //                        string strFieldName = strTmp.GetValue(0).ToString();
        //                        if (strValue != null && strValue != "")
        //                        {
        //                            if (strFieldName.Equals("±àÂë"))
        //                            {
        //                                //ĐÂÔöÊư¾ƯÊ±´¦Àí 
        //                                if (EditType != "SaveAttribute" && EditType != "UpdateGeo")
        //                                {
        //                                    if (EditLayer.Equals("ÈË¹¤Óă½¸Çø"))
        //                                    {
        //                                        strValue = getRGYJBH(resource, strValue, 6, 2);
        //                                    }
        //                                    if (EditLayer.Equals("·ÅÁ÷µØµă"))
        //                                    {
        //                                        strValue = getRGYJBH(resource, strValue, 6, 2);
        //                                    }
        //                                    if (EditLayer.Equals("ÈË¹¤Óă½¸¹æ»®"))
        //                                    {
        //                                        strValue = getRGYJBH(resource, strValue, 6, 2);
        //                                    }
        //                                }

        //                            }
        //                            int fieldIndex = feature.Fields.FindField(strFieldName);
        //                            feature.set_Value(fieldIndex, strValue);
        //                            //FieldItems.Add(strFieldName, strValue); 
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        string s = e.Message;
        //    }
        //}

        /// <summary> 
        /// Query layers at Envelope. 
        /// </summary> 
        /// <param name="map">Map control</param> 
        /// <param name="mapPoint">Map Envelope location</param> 
        public CallbackResult MapEdit(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map map, string xyString)
        {
            //#region Collections to store results 
            System.Collections.ArrayList identifyResults = new System.Collections.ArrayList(); //to send to client 
            //System.Collections.Generic.List<System.Data.DataSet>  gdsList = new System.Collections.Generic.List<System.Data.DataSet>(); //to store on server for "Add to Results" behavior 
            //#endregion 

            #region Variable declarations
            System.Collections.Generic.Dictionary<string, string> identifyResultItem; //a dictionary to hold info on a result item 
            ESRI.ArcGIS.ADF.Web.DataSources.IGISResource resource;
            ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality query;
            System.Data.DataTable[] identifyDataTables = null;
            string tableName;
            #endregion

            resource = map.MapResourceManagerInstance.ResourceItems.Find("̉µÎñÍ¼²ă").Resource;
            MapResourceLocal mapResourceLocal = resource as MapResourceLocal;

            ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality =
                (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)resource.CreateFunctionality(
                typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);



            //// Find the index of the query layer in the layer ID and name arrays 
            //int EditLayerIndex = PublicFun.getIntLayerID(commonQueryFunctionality, EditLayer);

            //IServerContext serverContext = mapResourceLocal.ServerContextInfo.ServerContext;
            //IMapServerObjects mso = (IMapServerObjects)mapResourceLocal.MapServer;
            //ILayer layer = mso.get_Layer(mapResourceLocal.MapServer.DefaultMapName, EditLayerIndex);


            //// Initialize a query filter to search the specified field for any values that begin with 
            //// the specified value. 

            //IFeatureLayer fl = (IFeatureLayer)layer;
            //IDataset dataset = fl.FeatureClass as IDataset;
            //IWorkspace workspace = dataset.Workspace;
            //IWorkspaceEdit wse = dataset.Workspace as IWorkspaceEdit;
            identifyResultItem = new System.Collections.Generic.Dictionary<string, string>();
            //try
            //{
            //    wse.StartEditing(false);
            //    wse.StartEditOperation();
            //    try
            //    {
            //        switch (EditType)
            //        {
            //            case "DelGeo":
            //                DelObjGeo(fl, ObjectID);
            //                break;
            //            case "SaveAttribute":
            //                SaveAttribute(resource, fl, ObjectID);
            //                break;
            //            case "UpdateGeo":
            //                UpdateGeo(map, resource, fl, xyString, ObjectID, serverContext);
            //                break;
            //            default:
            //                ObjectID = AddNew(map, resource, fl, xyString, serverContext);
            //                identifyResultItem.Add("ObjectID", ObjectID);
            //                break;
            //        }
            //    }
            //    catch (Exception e)
            //    {

            //    }
            //    wse.StopEditOperation();
            //    wse.StopEditing(true);
            //}
            //catch (Exception e)
            //{
            //    identifyResultItem.Add("Error", e.Message);
            //}
            identifyResults.Add(identifyResultItem);

            #region Create callback result to send to client
            //Note: arrays and dictionaries are handled natively by the JSON serialization framework 
            //return new CallbackResult(this, "mappoint", mapPoint.X, mapPoint.Y, identifyResults); 
            return new CallbackResult(this, "mappoint", identifyResults);
            #endregion
        }


        private System.Data.DataTable rowToTable(DataRow row, String tableName)
        {
            System.Data.DataTable table = new System.Data.DataTable(tableName);
            DataTable t = row.Table;
            for (int i = 0; i < t.Columns.Count; i++)
            {
                DataColumn c = t.Columns[i];
                DataColumn column = new DataColumn(c.ColumnName, c.DataType);
                table.Columns.Add(column);
            }

            DataRow r = table.NewRow();
            for (int i = 0; i < table.Columns.Count; i++)
            {
                r[i] = row[i];
            }
            table.Rows.Add(r);
            return table;
        }

        /// <summary> 
        /// Whether map has at least one resource that supports identify 
        /// </summary> 
        /// <returns></returns> 
        public bool SupportsIdentify()
        {
            ESRI.ArcGIS.ADF.Web.DataSources.IGISResource resource;
            ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality query;
            foreach (ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mapFunc in m_map.GetFunctionalities())
            {
                try
                {
                    resource = mapFunc.Resource;
                    query = resource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), "identify_") as ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality;
                    if ((query != null) && (query.Supports("Identify")))
                        return true;
                }
                catch
                {
                }
            }
            return false;
        }

        public void AddToTaskResults(int index)
        {
            if (m_taskResults == null)
                m_taskResults = FindControlRecursive(Page, m_taskResultsId) as TaskResults;
            if (m_taskResults != null)
            {
                System.Collections.Generic.List<System.Data.DataSet> gdsList =
                    System.Web.HttpContext.Current.Session["WebAppIdentifyDataSet"] as System.Collections.Generic.List<System.Data.DataSet>;
                if (gdsList != null && gdsList.Count > 0)
                {
                    System.Data.DataSet gds = gdsList[index] as System.Data.DataSet;
                    TaskResultNode tr = m_taskResults.CreateTaskResultNode(null, null, null, gds, false, true);
                    tr.Expanded = true;
                    m_taskResults.DisplayResults(null, null, null, tr);
                    this.CallbackResults.CopyFrom(m_taskResults.CallbackResults);
                }
            }
        }
        #region Properties

        public string Id
        {
            get { return m_id; }
            set { m_id = value; }
        }


        private MapResourceManager MapResourceManager
        {
            get { return m_resourceManger; }
            set { m_resourceManger = value; }
        }

        /// <summary> 
        /// Id of Buddy MapControl 
        /// </summary> 
        public string MapBuddyId
        {
            get { return m_mapBuddyId; }
            set { m_mapBuddyId = value; }
        }

        /// <summary> 
        /// Id of TaskResults Control 
        /// </summary> 
        public string TaskResultsId
        {
            get { return m_taskResultsId; }
            set { m_taskResultsId = value; }
        }

        public int NumberDecimals
        {
            get { return m_numberDecimals; }
            set { m_numberDecimals = value; }
        }


        #endregion


        #region ICallbackEventHandler Members

        public override string GetCallbackResult()
        {
            string resultsString = "";
            string responseString = _callbackArg;
            // break out the responseString into a querystring 
            Array keyValuePairs = responseString.Split("&".ToCharArray());
            NameValueCollection m_queryString = new NameValueCollection();
            string[] keyValue;
            string response = "";
            if (keyValuePairs.Length > 0)
            {
                for (int i = 0; i < keyValuePairs.Length; i++)
                {
                    keyValue = keyValuePairs.GetValue(i).ToString().Split("=".ToCharArray());
                    m_queryString.Add(keyValue[0], keyValue[1]);
                }
            }
            else
            {
                keyValue = responseString.Split("=".ToCharArray());
                if (keyValue.Length > 0)
                    m_queryString.Add(keyValue[0], keyValue[1]);
            }
            ESRI.ArcGIS.ADF.Web.UI.WebControls.Map map = Page.FindControl(this.m_mapBuddyId) as ESRI.ArcGIS.ADF.Web.UI.WebControls.Map;
            string mode = m_queryString["mode"];
            string dir = m_queryString["dir"];
            if (dir == "rtl") m_isRTL = true;
            switch (mode)
            {
                case "identify":
                    string xyString = m_queryString["coords"];
                    EditLayer = m_queryString["EditLayer"];
                    FieldsValue = m_queryString["FieldsValue"];
                    ObjectID = m_queryString["ObjectID"];
                    EditType = m_queryString["EditType"];
                    CallbackResult cResponse = MapEdit(map, xyString);
                    CallbackResults.Add(cResponse);
                    break;
                case "addresults":
                    string indexString = m_queryString["index"];
                    int index = Convert.ToInt32(indexString);
                    AddToTaskResults(index);
                    break;

            }
            return base.GetCallbackResult();
        }
        #endregion
    }
}